#ifndef CONVERTEX_H
#define CONVERTEX_H

#ifndef CORE_H
# include "..\..\inc\System\Core.h"
#endif

namespace Structs {

	class ConvertEx
	{
	private:
		static byte _getVariant9L(byte p[], ulong &v);
		static byte _getVaraint4(byte p[], uint &v);
	public:
		static byte GetVariantLength(ulong v);
		static inline byte GetVariant9(byte p[], int &v) { v = *p; if (v < 0x80) return 1; return _getVariant9L(p, (ulong&)v); }
        static inline byte GetVariant9(byte p[], uint &v) { v = *p; if (v < 0x80) return 1; return _getVariant9L(p, (ulong&)v); }
        static inline byte GetVariant9L(byte p[], long &v) { v = *p; if (v < 0x80) return 1; return _getVariant9L(p, (ulong&)v); }
        static inline byte GetVariant9L(byte p[], ulong &v) { v = *p; if (v < 0x80) return 1; return _getVariant9L(p, v); }
		static byte PutVariant9L(byte p[], ulong v);
		static inline byte PutVariant9(byte p[], int v) { return PutVariant9L(p, (ulong)v); }

		static inline byte GetVariant4(byte p[], int &v) { v = *p; if (v < 0x80) return 1; return _getVaraint4(p, (uint&)v); }
        static inline byte GetVariant4(byte p[], uint &v) { v = *p; if (v < 0x80) return 1; return _getVaraint4(p, v); }
		static inline byte GetVariant4(string p, int &v)
        {
            v = *p; if (v < 0x80) return 1;
            byte a[4];
            a[0] = (byte)p[0];
            a[1] = (byte)p[1];
            a[2] = (byte)p[2];
            a[3] = (byte)p[3];
            return _getVaraint4(a, (uint&)v);
        }
        static inline byte GetVaraint4(string p, uint &v)
        {
            v = *p; if (v < 0x80) return 1;
            byte a[4];
            a[0] = (byte)p[0];
            a[1] = (byte)p[1];
            a[2] = (byte)p[2];
            a[3] = (byte)p[3];
            return _getVaraint4(a, v);
        }
        static inline byte PutVariant4(byte p[], int v)
        {
            if ((v & ~0x7f) == 0) { *p = (byte)v; return 1; }
            if ((v & ~0x3fff) == 0) { *p = (byte)((v >> 7) | 0x80); p[1] = (byte)(v & 0x7f); return 2; }
            return PutVariant9(p, v);
        }

		static inline uint Get4(byte p[]) { return (uint)((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); }
        static inline void Put4(byte p[], int v)
        {
            p[0] = (byte)(v >> 24 & 0xFF);
            p[1] = (byte)(v >> 16 & 0xFF);
            p[2] = (byte)(v >> 8 & 0xFF);
            p[3] = (byte)(v & 0xFF);
        }
        static inline void Put4(byte p[], uint v)
        {
            p[0] = (byte)(v >> 24 & 0xFF);
            p[1] = (byte)(v >> 16 & 0xFF);
            p[2] = (byte)(v >> 8 & 0xFF);
            p[3] = (byte)(v & 0xFF);
        }
		static inline void Put4L(byte p[], long v)
        {
            p[0] = (byte)(v >> 24 & 0xFF);
            p[1] = (byte)(v >> 16 & 0xFF);
            p[2] = (byte)(v >> 8 & 0xFF);
            p[3] = (byte)(v & 0xFF);
        }
        static inline void Put4L(byte p[], ulong v)
        {
            p[0] = (byte)(v >> 24 & 0xFF);
            p[1] = (byte)(v >> 16 & 0xFF);
            p[2] = (byte)(v >> 8 & 0xFF);
            p[3] = (byte)(v & 0xFF);
        }
		
        inline static ushort Get2(byte p[]) { return (ushort)(p[0] << 8 | p[1]); }
		inline static ushort Get2nz(byte p[]) { return (ushort)(((((int)Get2(p)) - 1) & 0xffff) + 1); }
        inline static void Put2(byte p[], int v)
        {
            p[0] = (byte)(v >> 8);
            p[1] = (byte)v;
        }
        inline static void Put2(byte p[], uint v)
        {
            p[0] = (byte)(v >> 8);
            p[1] = (byte)v;
        }
	};
}

#endif // CONVERTEX_H